/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.ufg.inf.si.poo.formula1.Library;

import br.ufg.inf.si.poo.formula1.Circuit.Circuit;
import br.ufg.inf.si.poo.formula1.Driver.Driver;
import br.ufg.inf.si.poo.formula1.GUI.FrameMain;
import br.ufg.inf.si.poo.formula1.Race.GridPosition;
import br.ufg.inf.si.poo.formula1.Race.GridRace;
import br.ufg.inf.si.poo.formula1.Race.Qualification;
import br.ufg.inf.si.poo.formula1.Race.Race;
import br.ufg.inf.si.poo.formula1.Season.Season;
import br.ufg.inf.si.poo.formula1.Team.Team;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JList;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

/**
 * Library
 *
 * Versao 1.0
 *
 * Data 24/01/2013
 *
 * @author Severo
 */
public class Library {
    //Construtores
    private Library(){}

    //Outros Metodos
    /**
     * Gera um numero em milesimos de segundo aleatoriamente
     * entre 70000 = 1 minuto 10 segundos
     *     e 80000 = 1 minuto 30 segundos
     */
    public static long generatesTime() {
        Random random = new Random();
        long time = random.nextInt(10000) + 70000;

        return time;
    }
    
    /**
     * Gera um numero aleatorio de voltas
     * de 3 ate 12, e utilizado no SimulatorQualifiction
     */
    public static int generatesLaps() {
        Random random = new Random();
        int laps = random.nextInt(9) + 3;

        return laps;
    }

    /**
     * Converte valor de milisegundos para HORAS, MINUTOS ou SEGUNDOS, dependendo do parametro 'tipo'
     * @param timeInMillis, valor do tempo em milisegundo
     * @param tipo, o tipo diferenciara se o retorno sera em HORAS, MINUTOS ou SEGUNDOS
     * @return o tempo convertido para minutos
     */
    public static  String convertMilliseconds(long timeInMillis, String tipo) {
        long Millis = timeInMillis % 1000; //Pegamos os milisegundos
        int seconds = (int) ((timeInMillis / 1000) % 60); //Pegamos os segundos
        timeInMillis = (timeInMillis / 1000) / 60;
        int minutes = (int) (timeInMillis % 60); //Pegamos os minutos
        int horas = (int) (timeInMillis / 60);

        String data = "";
        int tamanho = 15;
        if("HORAS".equals(tipo)){
            data = horas + ":" + minutes + ":" + seconds + "." + Millis;
        }else if("MINUTOS".equals(tipo)) {
            data = (horas*60)+minutes + ":" + seconds + "." + Millis;
            tamanho = 8;
        }else{
            data = (horas*360)+(minutes*60)+seconds + "." + Millis;
            tamanho = 7;
        }
        return Library.setLengthString(data, tamanho);
    }

    /**
     * Edita a string passada como parametro e a retorna com o mesmo tamanho passado em 'length',
     * adiciona espacos se necessario
     * @param str, string a ser impressa
     * @param length, tamanho que deve ser impresso, caso a string não tenha este
     * tamanho, então irá imprimir espaços vazios
     * @return, string editada, recordata ou adicionado os espaços
     */
    public static String setLengthString(String str, int length) {
        if (str == null) {
            str = new String();
        }
        if (str.length() == length) {
            return str;
        } else if (str.length() < length) {
            char[] esp = new char[length - str.length()];
            Arrays.fill(esp, ' ');
            return str.concat(String.valueOf(esp));
        } else {
            return str.substring(0, length);
        }
    }
    
    /**
     * * Centraliza o Frame ou internalFrame passado como parametro
     * @param frame se for passado, ira centralizar o Frame de acordo com o Screen
     * @param internalFrame se for passado, ira centralizar o internalFrame de acordo com o JDesktopPane
     * @param desktopPane serve de parametro para centralizar o internalFrame
     */
    public static void centralizarFrameOrInternalFrame(JFrame frame, javax.swing.JDesktopPane desktopPane, JInternalFrame internalFrame){
        Toolkit tk = Toolkit.getDefaultToolkit();
        Dimension screenSize = tk.getScreenSize();

        if(internalFrame == null){
            int screenWidth = screenSize.width - frame.getWidth();
            int screenHeigth = screenSize.height - frame.getHeight();
            frame.setLocation(screenWidth/2, screenHeigth/2);
        }else{
            int screenWidth = desktopPane.getWidth() - internalFrame.getWidth();
            int screenHeigth = desktopPane.getHeight() - internalFrame.getHeight();
            internalFrame.setLocation(screenWidth/2, screenHeigth/2);
        }
        //setSize(screenSize.width,screenSize.height);
    }

    /**
     * Adiciona o ShortName em um JList, das equipes passadas no ArrayList
     * @param lista JList que sera mostrado os Shortname
     * @param team equipe que sera impresso o ShortName
     */
    public static void indexedListTeams(JList lista, ArrayList<Team> team, Season season){
        int quantidade = 0;
        if(team != null){
            quantidade = team.size();
        }else if(season != null){
            quantidade = season.getQttTeams();
        }
        String[] nomes = new String[quantidade];

        for (int i = 0; i < quantidade; i++) {
            if(team != null){
                if(team.get(i) != null){
                    nomes[i] = ""+team.get(i).getShortName();
                }
            }else if(season != null){
                if(season.getTeams()[i] != null){
                    nomes[i] = ""+season.getTeams()[i].getShortName();
                }
            } 
        }

        lista.setListData(nomes);
    }

    /**
     * Adiciona o Year em um JList, das temporada passadas no ArrayList
     * @param lista JList que sera mostrado os Shortname
     * @param season equipe que sera impresso o ShortName
     */
    public static void indexedListSeason(JList lista, ArrayList<Season> season){
        String[] nomes = new String[season.size()];

        for (int i = 0; i < nomes.length; i++) {
            if(season.get(i) != null){
                nomes[i] = ""+season.get(i).getYear();
            }
        }

        lista.setListData(nomes);
    }
    
    /**
     * Adiciona o Country em um JList, das circuitos passadas no ArrayList
     * @param lista JList que sera mostrado os Shortname
     * @param circuit equipe que sera impresso o ShortName
     */
    public static void indexedListCircuits(JList lista, ArrayList<Circuit> circuit, Season season){
        int quantidade = 0;
        if(circuit != null){
            quantidade = circuit.size();
        }else if(season != null){
            quantidade = season.getQttCircuits();
        }
        String[] nomes = new String[quantidade];

        for (int i = 0; i < quantidade; i++) {
            if(circuit != null){
                if(circuit.get(i) != null){
                    nomes[i] = ""+circuit.get(i).getCountry();
                }
            }else if(season != null){
                if(season.getCircuits()[i] != null){
                    nomes[i] = ""+season.getCircuits()[i].getCountry();
                }
            } 
        }

        lista.setListData(nomes);
    }

    /**
     * Adiciona o driverName em um JList, dos pilotos passadas no ArrayList
     * @param lista JList que sera mostrado os driverName
     * @param driver equipe que sera impresso o driverName
     * @param validaVinculacao caso seja true acrecentara se o piloto esta vinculado a uma equipe
     */
    public static void indexedListDrivers(JList lista, ArrayList<Driver> driver, Season season, Boolean validaVinculacao){
        int quantidade = 0;
        if(driver != null){
            quantidade = driver.size();
        }else if(season != null){
            quantidade = season.getQttDriver();
        }
        String[] nomes = new String[quantidade];

        for (int i = 0; i < quantidade; i++) {
            String texto = "";
            if(driver != null){
                if(driver.get(i) != null){
                    texto = driver.get(i).getDriverName();
                    if(validaVinculacao){
                        if(driver.get(i).getTeam() != null){
                            texto += " [Vinculado]";
                        }
                    }
                }
            }else if(season != null){
                if(season.getDriver()[i] != null){
                    texto = season.getDriver()[i].getDriverName();
                    if(validaVinculacao){
                        if(season.getDriver()[i].getTeam() != null){
                            texto += " [Vinculado]";
                        }
                    }
                }
            }
            nomes[i] = texto;
        }

        lista.setListData(nomes);
    }

    /**
     * Retorna um Objeto Equipe com mesmo nome passado como parametro
     * @param nome nome a ser pesquisado no ArrayList de equipes
     * @return retorna um Objeto equipe com mesmo nome passado como parametro
     */
    public static Team returnTeam(String name){
        for(int i = 0;i < FrameMain.getTeams().size();i++){
            if(FrameMain.getTeams().get(i).getShortName().equals(name)){
                return FrameMain.getTeams().get(i);
            }
        }
        return null;
    }
    
    /**
     * Retorna um Objeto Equipe com mesmo nome passado como parametro
     * @param nome nome a ser pesquisado no ArrayList de equipes
     * @return retorna um Objeto equipe com mesmo nome passado como parametro
     */
    public static Season returnSeason(int year){
        
        for(int i = 0;i < FrameMain.getSeasons().size();i++){
            if(FrameMain.getSeasons().get(i).getYear() == year){
                return FrameMain.getSeasons().get(i);
            }
        }
        return null;
    }

    /**
     * Retorna um Objeto Circuito com mesmo nome passado como parametro
     * @param nome nome a ser pesquisado no ArrayList de circuitos
     * @return retorna um Objeto circuito com mesmo nome passado como parametro
     */
    public static Circuit returnCircuit(String country){
        for(int i = 0;i < FrameMain.getCircuits().size();i++){
            if(FrameMain.getCircuits().get(i).getCountry().equals(country)){
                return FrameMain.getCircuits().get(i);
            }
        }
        return null;
    }

    /**
     * Retorna um Objeto Corrida com mesmo nome do pais do circuito como parametro
     * @param nome nome a ser pesquisado no ArrayList de corridas
     * @return retorna um Objeto circuito com mesmo nome passado como parametro
     */
    public static Race returnRace(String country){
        for(int i = 0;i < FrameMain.getCircuits().size();i++){
            if(FrameMain.getSeasonLoaded().getRace()[i] != null){
                if(FrameMain.getSeasonLoaded().getRace()[i].getCircuit() != null){
                    if(FrameMain.getSeasonLoaded().getRace()[i].getCircuit().getCountry().equals(country)){
                        return FrameMain.getSeasonLoaded().getRace()[i];
                    }
                }
            }
        }
        return null;
    }
    
    /**
     * Retorna um Objeto Piloto com mesmo nome passado como parametro
     * @param nome nome a ser pesquisado no ArrayList de circuitos
     * @return retorna um Objeto circuito com mesmo nome passado como parametro
     */
    public static Driver returnDriver(String driverName){
        for(int i = 0;i < FrameMain.getDrivers().size();i++){
            if(FrameMain.getDrivers().get(i).getDriverName().equals(driverName)){
                return FrameMain.getDrivers().get(i);
            }
        }
        return null;
    }

    /**
     * Insere os dados da qualificacao na JTable
     * @param table Tabela a ser apresentado os dados da qualificacao
     * @param race Corrida da qual sera apresentado os dados da qualificacao
     */
    public static void insertLinesTableQualification(JTable table, Race race) {
        DefaultTableModel modelo = (DefaultTableModel) table.getModel();
        while(modelo.getRowCount() > 0){
            modelo.removeRow(modelo.getRowCount()-1);
        }

        if (race != null) {
            Qualification qualification = race.getQualification();
            if (qualification != null) {
                //Lista Pilotos Vinculados
                for (int i = 0; i < qualification.getQttDrivers(); i++) {
                    GridPosition grid = qualification.getQualification()[i];
                    if (grid != null) {
                        //Library.setLengthString(this.race.getDrivers()[i].getDriverName(),15);
                        String Pos = "";

                        if(("DNQ".equals(grid.getStatus()))){
                            Pos = grid.getStatus();
                        }else{
                            Pos = ""+(i+1);
                        }
                        int No = grid.getNumberDriver();
                        Driver driver = grid.getDriver();
                        Team team = grid.getDriver().getTeam();
                        int Laps = grid.getQttLapsQualification();
                        String Q1 = Library.convertMilliseconds(grid.getQ1(), "MINUTOS");
                        String Q2 = Library.convertMilliseconds(grid.getQ2(), "MINUTOS");
                        String Q3 = Library.convertMilliseconds(grid.getQ3(), "MINUTOS");

                        modelo.addRow(new String[]{"", ""});
                        int linha = modelo.getRowCount();
                        linha--;
                        modelo.setValueAt(Pos, linha, 0);
                        modelo.setValueAt(No, linha, 1);
                        modelo.setValueAt(driver.getDriverName(), linha, 2);
                        modelo.setValueAt(team.getShortName(), linha, 3);
                        modelo.setValueAt(Q1, linha, 4);
                        modelo.setValueAt(Q2, linha, 5);
                        modelo.setValueAt(Q3, linha, 6);
                        modelo.setValueAt(Laps, linha, 7);
                    }
                }
            }
        }
    }

    /**
     * Insere os dados da corrida na JTable
     * @param table Tabela a ser apresentado os dados da corrida
     * @param race Corrida da qual sera apresentado os dados da corrida
     */
    public static void insertLinesTableRace(JTable table, Race race) {
        DefaultTableModel modelo = (DefaultTableModel) table.getModel();
        while(modelo.getRowCount() > 0){
            modelo.removeRow(modelo.getRowCount()-1);
        }

        if (race != null) {
            GridRace gridRace = race.getGridRace();
            if (gridRace != null) {
                //Lista Pilotos Vinculados
                long lessTime = 0;
                for (int i = 0; i < gridRace.getQttDrivers(); i++) {
                    GridPosition grid = gridRace.getGridRace()[i];
                    if (grid != null) {
                        if(i == 0){
                            lessTime = grid.timeTotal();
                        }
                        //Library.setLengthString(this.race.getDrivers()[i].getDriverName(),15);
                        String Pos = "";
                        if(("DNQ".equals(grid.getStatus()))){
                            Pos = grid.getStatus();
                        }else if(("Accident".equals(grid.getStatus()))
                        && grid.getQttLapsRace() < (grid.getQttLapsCircuit()*0.9)){
                            Pos = "Ret";
                        }else{
                            Pos = ""+(i+1);
                        }
                        int No = grid.getNumberDriver();
                        Driver driver = grid.getDriver();
                        Team team = grid.getDriver().getTeam();
                        String timeRace = "";
                        String Laps = ""+grid.getQttLapsRace();
                        String startingPosition = ""+grid.getStartingPosition();
                        String points = ""+grid.getPoints();

                        if(!("DNQ".equals(grid.getStatus()))){
                            if (i == 0) {
                                timeRace = Library.convertMilliseconds(lessTime, "HORAS");
                            } else if (!"Accident".equals(grid.getStatus())) {
                                long diferencaTempo = grid.timeTotal() - lessTime;
                                timeRace = Library.convertMilliseconds(diferencaTempo, "SEGUNDOS") + " secs" + "\t";
                            } else {
                                timeRace = "Accident" + "\t";
                            }
                        }else{
                            Laps = "";
                            timeRace = "";
                            startingPosition = "";
                            points = "";
                        }

                        modelo.addRow(new String[]{"", ""});
                        int linha = modelo.getRowCount();
                        linha--;

                        modelo.setValueAt(Pos, linha, 0);
                        modelo.setValueAt(No, linha, 1);
                        modelo.setValueAt(driver.getDriverName(), linha, 2);
                        modelo.setValueAt(team.getShortName(), linha, 3);
                        modelo.setValueAt(Laps,linha,4);
                        modelo.setValueAt(timeRace,linha,5);
                        modelo.setValueAt(startingPosition,linha,6);
                        modelo.setValueAt(points,linha,7);
                    }
                }
            }
        }
    }
}